import {VJson, VJsonProcess} from "./types";
import _ from 'lodash'
import {ApiFunction} from "./ajax";

export type FormatterFunction = (id: string) => string;

export type ValidFunction = (value: string) => string | ValidFunction | undefined;

export type ComplexValidFunction = (valid: string, value: string) => string | undefined;

export type ServerJsUrlTransformFunction = (jsUrl: string) => string | undefined;

let debugMode: boolean = false

/**
 * 字典项
 */
export interface DictItem {
    id: string;
    text: string;

    [id: string]: string;
}

/**
 * 字典
 */
export type Dict = DictItem[];

/**
 * YvanUI 全局扩展配置
 */
export interface ExtendOption {

    /**
     * react-dom 渲染函数
     */
    debugMode: boolean

    /**
     * 扩展自定义的 vjson 运行时 修改
     */
    beforeResolverVJson: (module: any, vJson: VJson) => VJson;

    /**
     * 扩展 onLoad方法后执行
     */
    afterModuleRender: (module: any) => void;

    /**
     * 扩展自定义的 ajax 方法
     */
    ajax: ApiFunction;

    /**
     * serverJS Url转换为Ajax请求
     */
    serverJsUrlTransform: ServerJsUrlTransformFunction;

    /**
     * 扩展全局 formatter 函数
     */
    formatter: { [db: string]: FormatterFunction };

    /**
     * 扩展全局 dict 字典
     */
    dict: { [dictName: string]: Dict };

    /**
     * 扩展全局 校验方法
     */
    validType: { [validName: string]: ValidFunction };

    /**
     * 复杂校验通用方法
     */
    complexValid: { [validName: string]: ComplexValidFunction };

    /**
     * 组件渲染过滤器, 如果方法返回 false 代表该组件不需要被渲染.
     * 可以修改 vjson 的内容，但不能删除他
     */
    componentRenderFilter: (vjson: any) => undefined | boolean

    /**
     * 调用 YvanScope.showPage 时，自定义的打开方式
     */
    showPageOption: (title: string, key: string, jsr: any) => void

    /**
     * page 请求关闭时触发
     */
    closePageOption: (jsr: any) => void

    /**
     * 获取拼音首字母的函数
     */
    pinyinFunction: (py: string) => string

    /**
     * 需要添加的 VJsonProcess 处理过程
     */
    vjsonProcess: VJsonProcess
}

/**
 * 全局 vjson 运行时
 */
export let beforeResolverVJson: (undefined | ((module: any, vJson: VJson) => VJson)) = undefined;

export let afterModuleRender: (undefined | ((module: any) => void)) = undefined;

/**
 * 全局 ajax 方法
 */
export const ajax: {
    func?: ApiFunction
} = {}

/**
 * 全局 formatter 函数
 */
export const formatter: { [db: string]: FormatterFunction } = {};

/**
 * 全局 dict 字典
 */
export const dict: { [dictName: string]: Dict } = {};

/**
 * 全局 校验方法
 */
export const validType: { [validName: string]: ValidFunction } = {};

/**
 * 复杂校验通用方法
 */
export const complexValid: { [validName: string]: ComplexValidFunction } = {};

/**
 * 组件渲染过滤器, 如果方法返回 false 代表该组件不需要被渲染.
 * 可以修改 vjson 的内容，但不能删除他
 */
export let componentRenderFilter: (undefined | ((vjson: any) => undefined | boolean)) = undefined;

export let showPageOption: (title: any, key: string, jsr: any) => void

export let closePageOption: (jsr: any) => void

export const vjsonProcessChain: VJsonProcess[] = []

export function serverJsUrlTransform(url: string) {
    return _.get(window, '_YvanUI_serverJSPrefix')(url);
}

/**
 * 添加一个 VJson 的处理过程
 * @param func VJson 处理函数
 */
export function pushVJsonProcess(func: VJsonProcess) {
    if (isDebugMode()) {
        console.log('pushVJsonProcess', func)
    }
    vjsonProcessChain.push(func)
}

/**
 * 注册一个 VJson 处理过程
 * @param func 一个 vjsonProcessChain 处理函数
 */
export function registeVJsonProcess(func: (list: VJsonProcess[]) => void) {
    func(vjsonProcessChain)
}

/**
 * YvanUI 全局扩展配置
 * @param option 配置信息
 */
export function extend(option: Partial<ExtendOption>) {
    if (option.beforeResolverVJson) {
        beforeResolverVJson = option.beforeResolverVJson
    }

    if (option.afterModuleRender) {
        afterModuleRender = option.afterModuleRender;
    }

    if (option.ajax) {
        ajax.func = option.ajax
    }

    if (option.serverJsUrlTransform) {
        _.extend(window, {_YvanUI_serverJSPrefix: option.serverJsUrlTransform});
    }

    if (option.dict) {
        _.extend(dict, option.dict);
    }

    if (option.validType) {
        _.extend(validType, option.validType);
    }

    if (option.formatter) {
        _.extend(formatter, option.formatter);
    }

    if (option.complexValid) {
        _.extend(complexValid, option.complexValid);
    }

    if (option.componentRenderFilter) {
        componentRenderFilter = option.componentRenderFilter
    }

    if (option.showPageOption) {
        showPageOption = option.showPageOption
    }

    if (option.closePageOption) {
        closePageOption = option.closePageOption
    }

    if (option.pinyinFunction) {
        pinyinFunc = option.pinyinFunction
    }

    if (typeof option.debugMode !== 'undefined') {
        setDebugMode(option.debugMode)
    }

    if (option.vjsonProcess) {
        pushVJsonProcess(option.vjsonProcess)
    }
}

export function isDebugMode(): boolean {
    return debugMode
}

export function setDebugMode(v: boolean) {
    debugMode = v
}

let pinyinFunc: Function

export function getPinyin(v: string) {
    return pinyinFunc(v)
}

/**
 * 适用于 Select / Tree 等，作筛选的通用方法.
 * 1.首字母模糊匹配（不区分大小写）
 * 2.标识的模糊匹配（不区分大小写）
 * 3.名称的模糊匹配，且支持以逗号（全角或半角）隔开的字词匹配，并自动去空格，如“南京， 物流 ”可以匹配出“南京九州通物流技术开发有限公司”
 */
export function keywordFilter(keyword: string, label: string, value?: string) {
    if (!keyword) {
        return true
    }
    const ws = _.trim(keyword).split(/\s+|\.|,|\)|\(|，|。|-|—/g)
    const labelPy = _.toLower(getPinyin(label))
    value = _.toLower(_.trim(value))

    let found = 0
    _.some(ws, (word) => {
        if (labelPy.indexOf(word.toLowerCase()) >= 0 || label.indexOf(word) >= 0) {
            found++
            return
        }

        if (value && value.indexOf(word.toLowerCase()) >= 0) {
            found++
            return
        }
    })

    return found >= ws.length
}